package com.loser.utils;

import com.loser.utils.trace.MDCUtil;
import com.loser.utils.trace.TraceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.concurrent.ExecutorService;

/**
 * 异步工具
 *
 * @author alan
 * @date 2021/12/13 20:30
 */
public class AsyncUtil {

    private static final Logger log = LoggerFactory.getLogger(AsyncUtil.class);

    /**
     * 异步执行方法
     */
    public static void asyncExecute(ExecutorService service, Runnable runnable) {

        service.execute(() -> {
            try {
                MDCUtil.setTraceId();
                runnable.run();
            } catch (Exception e) {
                log.error("asyncExecute throw a e", e);
            } finally {
                MDCUtil.removeTraceId();
            }
        });

    }


    /**
     * 异步执行方法 为不同的线程设置相同的 traceId
     */
    public static void asyncExecute(ExecutorService service, String traceId, Runnable runnable) {

        service.execute(() -> {
            try {
                MDCUtil.setTraceId(traceId);
                runnable.run();
            } catch (Exception e) {
                log.error("asyncExecute throw a e", e);
            } finally {
                MDCUtil.removeTraceId();
            }
        });

    }

    /**
     * 异步执行方法
     */
    public static void async(ExecutorService service, Runnable runnable) {

        String traceId = MDCUtil.getTraceId();
        traceId = StringUtils.isEmpty(traceId) ? TraceUtil.getTraceId() : traceId;
        asyncExecute(service, traceId, runnable);

    }

    /**
     * 异步执行方法
     */
    public static void asyncExecute(Runnable runnable) {

        ConstExecutor.EXECUTOR_IMPORTANT.execute(() -> {
            try {
                MDCUtil.setTraceId();
                runnable.run();
            } catch (Exception e) {
                log.error("asyncExecute throw a e", e);
            } finally {
                MDCUtil.removeTraceId();
            }
        });

    }

    /**
     * 异步执行方法 为不同的线程设置相同的 traceId
     */
    public static void asyncExecute(String traceId, Runnable runnable) {

        ConstExecutor.EXECUTOR_IMPORTANT.execute(() -> {
            try {
                MDCUtil.setTraceId(traceId);
                runnable.run();
            } catch (Exception e) {
                log.error("asyncExecute throw a e", e);
            } finally {
                MDCUtil.removeTraceId();
            }
        });

    }

    /**
     * 异步执行方法
     */
    public static void async(Runnable runnable) {

        String traceId = MDCUtil.getTraceId();
        traceId = StringUtils.isEmpty(traceId) ? TraceUtil.getTraceId() : traceId;
        asyncExecute(traceId, runnable);

    }

}
